﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Windows.ApplicationModel.Store;

namespace Undercover.Model
{
    public class Treasure
    {
        public static Lazy<Treasure> Global = new Lazy<Treasure>(() => Treasure.Load(App.TreasurePath), false);

        /// <summary>
        /// Gets the word packages.
        /// </summary>
        public IReadOnlyList<WordPackage> WordPackages
        {
            get
            {
                if (_wordPackages == null)
                {
                    _wordPackages = new List<WordPackage>();
                }
                return _wordPackages;
            }
        }
        private List<WordPackage> _wordPackages;

        /// <summary>
        /// The use count of the word from the selected packages.
        /// </summary>
        public int UseCount
        {
            get
            {
                return WordPackages.Where(it => it.Selected).Sum(it => it.UseWordCount);
            }
        }

        /// <summary>
        /// The total count of the word from the selected packages.
        /// </summary>
        public int TotalCount
        {
            get
            {
                return WordPackages.Where(it => it.Selected).Sum(it => it.WordCount);
            }
        }

        public Treasure()
        {
        }

        public void AddPackage(WordPackage package)
        {
            if (package == null)
            {
                throw new ArgumentNullException();
            }

            _wordPackages.Add(package);
        }

        public WordPair PickUp()
        {
            List<WordPair> available = new List<WordPair>();
            foreach (var package in _wordPackages.Where(it => it.Selected && it.Purchased))
            {
                foreach (var pair in package.GetWordPairList())
                {
                    if (pair.UseCount == 0)
                    {
                        available.Add(pair);
                    }
                }
            }

            if (available.Count == 0)
            {
                return null;
            }

            return available[random.Next(available.Count)];
        }

        public static Treasure Load(string path)
        {
            Treasure ret = new Treasure();
            ret._wordPackages = new List<WordPackage>();
            
            // load from local storage
            try
            {
                using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(path, FileMode.Open, FileAccess.Read, file))
                {
                    var reader = new StreamReader(stream);
                    XmlSerializer xs = new XmlSerializer(typeof(List<WordPackage>));
                    ret._wordPackages.AddRange((List<WordPackage>)xs.Deserialize(reader));
                }
            }
            catch { }
            finally { }

            // generate a new default one
            if (ret._wordPackages.Count==0)
            {
                foreach (var p in WordPackage.GetInternalPackages())
                {
                    ret._wordPackages.Add(p);
                }
            }

            return ret;
        }

        public void Save(string path)
        {
            using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(path,
                FileMode.Create, FileAccess.Write, file))
            {
                XmlSerializer xml = new XmlSerializer(typeof(List<WordPackage>));
                xml.Serialize(stream, _wordPackages);
            }
        }

        private static Random random = new Random((int)DateTime.UtcNow.Ticks);
    }
}
